﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver.Linq;
using MongoDB.Driver.Builders;
using System.Diagnostics;


namespace MongoPerfTest
{
    static class RatingRanking
    {

        static public void RunRating(/*List<Guid> ids, Guid matrixId*/)
        {
            var client = new MongoClient("mongodb://localhost");
            var server = client.GetServer();
            var mongo = server.GetDatabase("MongoTestPerf");
            //var jscript = System.IO.File.ReadAllLines("Rating.js");
            //var pureJS = new StringBuilder();
            //foreach(var s in jscript)
            //{
            //    var pos = s.IndexOf("//");
            //    if (pos == -1)
            //    {
            //        pureJS.Append(s);
            //    }
            //    else
            //    {
            //        pureJS.Append(s.Substring(0, pos));
            //    }
            //}
            //  elems.Add(BsonDocument.Parse(pureJS.ToString()));

            var rankFunction = System.IO.File.ReadAllText("ranking2.js");

            var elems = new List<BsonDocument>();
            try
            {

                var step1 = BsonDocument.Parse(System.IO.File.ReadAllText("rating1.js"));
                var step2 = BsonDocument.Parse(System.IO.File.ReadAllText("rating2.js"));
                var step3 = BsonDocument.Parse(System.IO.File.ReadAllText("rating3.js"));
                var step4 = BsonDocument.Parse("{$sort:  { ParentGroupId: 1, CompanyScore: 1 }}");
                var step5 = BsonDocument.Parse(System.IO.File.ReadAllText("ranking1.js"));
                               
                elems.Add(step1);
                elems.Add(step2);
                elems.Add(step3);
                elems.Add(step4);
                elems.Add(step5);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            var dropNames = mongo.GetCollectionNames().Where(x => x.Contains("_out"));
            foreach (var c in dropNames)
                mongo.DropCollection(c);


            var collectionNames = mongo.GetCollectionNames().Where(x => x.StartsWith("MatrixId_") && !x.Contains("_out") && !x.Contains("_avg"));
            if (collectionNames.Count() != 176)
                return;

            
            Action<string> ratingAction = (string collectionName) =>
                                {
                                    try 
                                    {
                                        var client1 = new MongoClient("mongodb://localhost");
                                        var server1 = client.GetServer();
                                        var mongo1 = server.GetDatabase("MongoTestPerf");


                                        // compute ratings
                                        var local =  new List<BsonDocument>(elems);
                                        local.Add(new BsonDocument("$out", collectionName + "_out"));
                                        var collection = mongo1.GetCollection(collectionName);
                                        var stopWatch = new Stopwatch();
                                        stopWatch.Start();
                                        /*var result =*/ 
                                        collection.Aggregate(new AggregateArgs() { Pipeline = local });

                                        

                                        // //compute ranking  
                                        //var collectionOut = mongo1.GetCollection(collectionName + "_out");
                                        //collectionOut.MapReduce(new MapReduceArgs()
                                        //{
                                        //    OutputCollectionName = collectionName + "_out2",
                                        //    OutputMode = MapReduceOutputMode.Replace,
                                        //    MapFunction = new BsonJavaScript(rankFunction),
                                        //    ReduceFunction = new BsonJavaScript(""), 
                                        //});

                                        stopWatch.Stop();
                                        Console.WriteLine("Processing " + collectionName + " took " +
                                            stopWatch.Elapsed.TotalMilliseconds.ToString() + " result: " /* + result.Count()*/);                   
                                    }
                                    catch(Exception ex)
                                    {
                                        Console.WriteLine(ex.ToString());
                                    }         
                                };

            Action<string> percentAction = (string collectionName) =>
            {
                try
                {
                    
                    var client1 = new MongoClient("mongodb://localhost");
                    var server1 = client.GetServer();
                    var mongo1 = server.GetDatabase("MongoTestPerf");
                    var stopWatch = new Stopwatch();
                    stopWatch.Start();

                     //compute ranking  
                    var collectionOut = mongo1.GetCollection(collectionName + "_out");
                    collectionOut.MapReduce(new MapReduceArgs()
                    {
                        OutputCollectionName = collectionName + "_out",
                        OutputMode = MapReduceOutputMode.Replace,
                        MapFunction = new BsonJavaScript(rankFunction),
                        ReduceFunction = new BsonJavaScript(""),
                    });

                    stopWatch.Stop();
                    Console.WriteLine("Processing " + collectionName + "_out" + " took " +
                        stopWatch.Elapsed.TotalMilliseconds.ToString() + " result: " /* + result.Count()*/);    

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            };



            {                
                    var stopWatch = new Stopwatch();
                    stopWatch.Start();
                    ratingAction("MatrixId_00000000-0000-0000-0000-000000000000");
                    percentAction("MatrixId_00000000-0000-0000-0000-000000000000");
                    Parallel.ForEach(collectionNames, ratingAction);
                    Parallel.ForEach(collectionNames, percentAction);
                    stopWatch.Stop();
                    Console.WriteLine("Processing MongoTestPerf took " + stopWatch.Elapsed.TotalMilliseconds.ToString());   
            }           

        }

        static  public void RunRanking(List<Guid> ids, Guid matrixId)
        {

        }

    }
}
